package org.budo.dubbo.http.client.java;

import org.budo.dubbo.http.client.java.callback.AbstractCallback;
import org.budo.dubbo.http.client.java.callback.MergedCallback;
import org.budo.dubbo.http.client.java.exception.ApiErrorException;

/**
 * @author lmw-2
 */
public class Deferred extends RequestContext {
    /**
     * 异步执行
     */
    public void then(final AbstractCallback apiCallback) {
        this.getExecutorService().submit(new Runnable() {
            public void run() {
                Deferred.this.doRequest(apiCallback);
            }
        });
    }

    /**
     * 同步执行返回结果
     */
    public Object result() {
        this.setAsync(false);
        ResponseHandler responseHandler = this.getResponseHandler();

        try {
            String responseBody = this.doRequest();
            this.setResponseBody(responseBody);
            return responseHandler.handleResponse(this);
        } catch (Throwable e) {
            throw e instanceof ApiErrorException ? (ApiErrorException) e : new ApiErrorException(e);
        }
    }

    /**
     * 同步发起请求,返回结果,可能会有异常
     */
    private String doRequest() {
        RequestFilter requestFilter = this.getRequestFilter();
        if (null != requestFilter) {
            requestFilter.doFilter(this);
        }

        Transporter transporter = this.getTransporter();
        return transporter.request(this);
    }

    /**
     * 发起请求并用回调处理结果
     */
    private void doRequest(AbstractCallback apiCallback) {
        this.setAsync(true);
        this.setApiCallback(new MergedCallback(apiCallback, this.getApiCallback())); // 合并回调
        ResponseHandler responseHandler = this.getResponseHandler();

        try {
            String responseBody = this.doRequest();
            this.setResponseBody(responseBody);
            responseHandler.handleResponse(this); // 成功回调
        } catch (Throwable e) {
            this.setException(e);
            responseHandler.handleResponse(this); // 失败回调
        }
    }
}